<template>
  <div :class="getClass" ref="wrapperRef">
    <PageHeader
        :ghost="ghost"
        :title="title"
        v-bind="obj"
        ref="headerRef"
        v-if="getShowHeader"
    >
      <template #default>
        <template v-if="content">
          {{ content }}
        </template>
        <slot name="headerContent" v-else></slot>
      </template>
      <template #[item]="data" v-for="item in getHeaderSlots">
        <slot :name="item" v-bind="data || {}"></slot>
      </template>
    </PageHeader>

    <div
        class="overflow-hidden"
        :class="getContentClass"
        :style="getContentStyle"
        ref="contentRef"
    >
      <slot></slot>
    </div>

    <PageFooter v-if="getShowFooter" ref="footerRef">
      <template #left>
        <slot name="leftFooter"></slot>
      </template>
      <template #right>
        <slot name="rightFooter"></slot>
      </template>
    </PageFooter>
  </div>
</template>
<script lang="ts">
import {CSSProperties, PropType, provide} from 'vue'

import {defineComponent, computed, watch, ref, unref} from 'vue'
import PageFooter from './PageFooter.vue'
import {useDesign} from '@/hooks/web/useDesign'
import {omit} from '@pkg/utils'
import {PageHeader} from 'ant-design-vue'
import {useContentHeight} from './useContentHeight'
import {PageWrapperFixedHeightKey} from '..'

export default defineComponent({
  name: 'PageWrapper',
  components: {PageFooter, PageHeader},
  inheritAttrs: false,
  props: {
    title: {type: String},
    dense: {type: Boolean},
    ghost: {type: Boolean},
    content: {type: String},
    contentStyle: {
      type: Object as PropType<CSSProperties>,
    },
    contentBackground: {type: Boolean},
    contentFullHeight: {type: Boolean},
    contentClass: {type: String},
    fixedHeight: {type: Boolean},
    upwardSpace: {
      type: [String, Number],
      default: 0,
    },
  },
  setup(props, {slots, attrs}) {
    const wrapperRef = ref(null)
    const headerRef = ref(null)
    const contentRef = ref(null)
    const footerRef = ref(null)
    const {prefixCls} = useDesign('page-wrapper')
    const obj:any=omit(attrs, 'class')

    provide(
        PageWrapperFixedHeightKey,
        computed(() => props.fixedHeight),
    )

    const getIsContentFullHeight = computed(() => {
      return props.contentFullHeight
    })

    const getUpwardSpace = computed(() => props.upwardSpace)
    const {redoHeight, setCompensation, contentHeight} = useContentHeight(
        getIsContentFullHeight,
        wrapperRef,
        [headerRef, footerRef],
        [contentRef],
        getUpwardSpace,
    )
    setCompensation({useLayoutFooter: true, elements: [footerRef]})

    const getClass = computed(() => {
      return [
        prefixCls,
        {
          [`${prefixCls}--dense`]: props.dense,
        },
        attrs.class ?? {},
      ]
    })

    const getShowHeader = computed(
        () =>
            props.content ||
            slots?.headerContent ||
            props.title ||
            getHeaderSlots.value.length,
    )

    const getShowFooter = computed(
        () => slots?.leftFooter || slots?.rightFooter,
    )

    const getHeaderSlots = computed(() => {
      return Object.keys(
          omit(slots, 'default', 'leftFooter', 'rightFooter', 'headerContent'),
      )
    })

    const getContentStyle = computed((): CSSProperties => {
      const {contentFullHeight, contentStyle, fixedHeight} = props
      if (!contentFullHeight) {
        return {...contentStyle}
      }

      const height = `${unref(contentHeight)}px`
      return {
        ...contentStyle,
        minHeight: height,
        ...(fixedHeight ? {height} : {}),
      }
    })

    const getContentClass = computed(() => {
      const {contentBackground, contentClass} = props
      return [
        `${prefixCls}-content`,
        contentClass,
        {
          [`${prefixCls}-content-bg`]: contentBackground,
        },
      ]
    })

    watch(
        () => [getShowFooter.value],
        () => {
          redoHeight()
        },
        {
          flush: 'post',
          immediate: true,
        },
    )

    return {
      getContentStyle,
      obj,
      wrapperRef,
      headerRef,
      contentRef,
      footerRef,
      getClass,
      getHeaderSlots,
      prefixCls,
      getShowHeader,
      getShowFooter,
      getContentClass
    }
  },
})
</script>
<style lang="less">
@prefix-cls: ~'@{namespace}-page-wrapper';

.@{prefix-cls} {
  position: relative;

  .@{prefix-cls}-content {
    margin: 16px;
  }

  .ant-page-header {
    &:empty {
      padding: 0;
    }
  }

  &-content-bg {
    background-color: @component-background;
  }

  &--dense {
    .@{prefix-cls}-content {
      margin: 0;
    }
  }
}
</style>
